home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / Matrix.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  19KB  |  790 lines

  1. /*
  2. **    Matrix.c
  3. **
  4. **    Single character entry
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14. typedef struct MatrixInfo
  15. {
  16.     UWORD             CellWidth,
  17.                      CellHeight;
  18.     UWORD             Width,
  19.                      Height;
  20.     UWORD             PixelWidth,
  21.                      PixelHeight;
  22.     WORD             CurrentX,
  23.                      CurrentY;
  24.     STRPTR            *Labels;
  25.     LONG             NumLabels;
  26.     struct TextFont    *Font;
  27.     LONG             CurrentIndex;
  28. } MatrixInfo;
  29.  
  30. #define MIA_CellWidth    (TAG_USER+0x70000)
  31. #define MIA_CellHeight    (TAG_USER+0x70001)
  32. #define MIA_Width        (TAG_USER+0x70002)
  33. #define MIA_Height        (TAG_USER+0x70003)
  34. #define MIA_Labels        (TAG_USER+0x70004)
  35. #define MIA_NumLabels    (TAG_USER+0x70005)
  36. #define MIA_Font        (TAG_USER+0x70006)
  37. #define MIA_Index        (TAG_USER+0x70007)
  38.  
  39. STATIC struct IClass    *MatrixClass;
  40. STATIC Object            *MatrixGadget;
  41.  
  42. STATIC UBYTE             TitleBuffer[256];
  43.  
  44. STATIC VOID __regargs
  45. DrawCellText(struct RastPort *RPort,UWORD Left,UWORD Top,UWORD Width,UWORD Height,STRPTR Label)
  46. {
  47.     struct TextExtent    Extent;
  48.     LONG                Len = strlen(Label);
  49.  
  50.     if(Len = TextFit(RPort,Label,Len,&Extent,NULL,1,Width,32767))
  51.     {
  52.         Move(RPort,Left + (Width - Extent . te_Width) / 2,Top + (Height - Extent . te_Height) / 2 + RPort -> TxBaseline);
  53.         Text(RPort,Label,Len);
  54.     }
  55. }
  56.  
  57. STATIC VOID __regargs
  58. DrawCell(struct RastPort *RPort,UWORD PixelLeft,UWORD PixelTop,struct GadgetInfo *GadgetInfo,MatrixInfo *Info,UWORD x,UWORD y,BOOL Highlight)
  59. {
  60.     UWORD    Left,Top;
  61.     UWORD    Shine,Shadow,Text,Fill;
  62.     LONG    Index;
  63.  
  64.     Left    = PixelLeft    + Info->CellWidth    * x;
  65.     Top        = PixelTop    + Info->CellHeight    * y;
  66.  
  67.     if(Highlight)
  68.     {
  69.         Shine    = GadgetInfo->gi_DrInfo->dri_Pens[SHADOWPEN];
  70.         Shadow    = GadgetInfo->gi_DrInfo->dri_Pens[SHINEPEN];
  71.         Text    = GadgetInfo->gi_DrInfo->dri_Pens[FILLTEXTPEN];
  72.         Fill    = GadgetInfo->gi_DrInfo->dri_Pens[FILLPEN];
  73.     }
  74.     else
  75.     {
  76.         Shine    = GadgetInfo->gi_DrInfo->dri_Pens[SHINEPEN];
  77.         Shadow    = GadgetInfo->gi_DrInfo->dri_Pens[SHADOWPEN];
  78.         Text    = GadgetInfo->gi_DrInfo->dri_Pens[TEXTPEN];
  79.         Fill    = GadgetInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN];
  80.     }
  81.  
  82.     SetDrMd(RPort,JAM1);
  83.  
  84.     SetAPen(RPort,Shine);
  85.     Move(RPort,Left,Top + Info->CellHeight - 1);
  86.     Draw(RPort,Left,Top);
  87.     Draw(RPort,Left + Info->CellWidth - 1,Top);
  88.  
  89.     SetAPen(RPort,Shadow);
  90.     Move(RPort,Left + 1,Top + Info->CellHeight - 1);
  91.     Draw(RPort,Left + Info->CellWidth - 1,Top + Info->CellHeight - 1);
  92.     Draw(RPort,Left + Info->CellWidth - 1,Top + 1);
  93.  
  94.     SetAPen(RPort,Fill);
  95.     RectFill(RPort,Left + 1,Top + 1,Left + Info->CellWidth - 2,Top + Info->CellHeight - 2);
  96.  
  97.     if((Index = y * Info->Width + x) < Info->NumLabels)
  98.     {
  99.         SetAPen(RPort,Text);
  100.         DrawCellText(RPort,Left + 1,Top + 1,Info->CellWidth - 2,Info->CellHeight - 2,Info->Labels[Index]);
  101.     }
  102. }
  103.  
  104. STATIC VOID __regargs
  105. DrawGrid(struct RastPort *RPort,UWORD PixelLeft,UWORD PixelTop,struct GadgetInfo *GadgetInfo,MatrixInfo *Info)
  106. {
  107.     UWORD i,j,Left,Top,Bottom,Strange,Charm;
  108.  
  109.     SetDrMd(RPort,JAM1);
  110.  
  111.     Left    = PixelLeft;
  112.     Top        = PixelTop;
  113.     Bottom    = PixelTop + Info->PixelHeight - 1;
  114.  
  115.     Strange    = GadgetInfo->gi_DrInfo->dri_Pens[SHINEPEN];
  116.     Charm    = GadgetInfo->gi_DrInfo->dri_Pens[SHADOWPEN];
  117.  
  118.     for(i = 0 ; i < Info->Width ; i++)
  119.     {
  120.         SetAPen(RPort,Strange);
  121.         Move(RPort,Left,Top);
  122.         Draw(RPort,Left,Bottom);
  123.  
  124.         Left += Info->CellWidth;
  125.  
  126.         SetAPen(RPort,Charm);
  127.         Move(RPort,Left - 1,Top);
  128.         Draw(RPort,Left - 1,Bottom);
  129.     }
  130.  
  131.     Top = PixelTop;
  132.  
  133.     for(j = 0 ; j < Info->Height ; j++)
  134.     {
  135.         Left = PixelLeft;
  136.  
  137.         for(i = 0 ; i < Info->Width ; i++)
  138.         {
  139.             SetAPen(RPort,Strange);
  140.             Move(RPort,Left,Top);
  141.             Draw(RPort,Left + Info->CellWidth - 1,Top);
  142.  
  143.             SetAPen(RPort,Charm);
  144.             Move(RPort,Left + 1,Top + Info->CellHeight - 1);
  145.             Draw(RPort,Left + Info->CellWidth - 2,Top + Info->CellHeight - 1);
  146.  
  147.             Left += Info->CellWidth;
  148.         }
  149.  
  150.         Top += Info->CellHeight;
  151.     }
  152. }
  153.  
  154. STATIC VOID __regargs
  155. NotifyIndex(struct IClass *class,Object *object,struct GadgetInfo *GInfo,struct opUpdate *msg,LONG Index)
  156. {
  157.     struct TagItem Tags[3];
  158.  
  159.     Tags[0] . ti_Tag    = MIA_Index;
  160.     Tags[0] . ti_Data    = Index;
  161.     Tags[1] . ti_Tag    = GA_ID;
  162.     Tags[1] . ti_Data    = ((struct Gadget *)object)->GadgetID;
  163.     Tags[2] . ti_Tag    = TAG_DONE;
  164.  
  165.     DoSuperMethod(class,object,OM_NOTIFY,Tags,GInfo,((msg->MethodID == OM_UPDATE) ? (msg->opu_Flags) : 0L));
  166. }
  167.  
  168. STATIC ULONG __regargs
  169. SetMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
  170. {
  171.     MatrixInfo        *Info = INST_DATA(class,object);
  172.     struct TagItem    *Tag;
  173.  
  174.     if(Tag = FindTagItem(MIA_Index,SetInfo -> ops_AttrList))
  175.     {
  176.         struct RastPort *RPort;
  177.  
  178.         if(RPort = ObtainGIRPort(SetInfo->ops_GInfo))
  179.         {
  180.             LONG Index = (LONG)Tag -> ti_Data;
  181.  
  182.             SetFont(RPort,Info->Font);
  183.  
  184.             if(Info->CurrentX != -1 && Info->CurrentY !=-1)
  185.                 DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,SetInfo->ops_GInfo,Info,Info->CurrentX,Info->CurrentY,FALSE);
  186.  
  187.             if(Index >= 0 && Index < Info->Width * Info->Height)
  188.             {
  189.                 Info->CurrentX = Index % Info->Width;
  190.                 Info->CurrentY = Index / Info->Width;
  191.  
  192.                 DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,SetInfo->ops_GInfo,Info,Info->CurrentX,Info->CurrentY,TRUE);
  193.  
  194.                 NotifyIndex(class,object,SetInfo->ops_GInfo,(struct opUpdate *)SetInfo,Index);
  195.             }
  196.             else
  197.             {
  198.                 Info->CurrentX = Info->CurrentY = -1;
  199.  
  200.                 NotifyIndex(class,object,SetInfo->ops_GInfo,(struct opUpdate *)SetInfo,-1);
  201.             }
  202.  
  203.             ReleaseGIRPort(RPort);
  204.         }
  205.     }
  206.  
  207.     return(DoSuperMethodA(class,object,(Msg)SetInfo));
  208. }
  209.  
  210. STATIC ULONG __regargs
  211. RenderMethod(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  212. {
  213.     MatrixInfo    *Info = INST_DATA(class,object);
  214.     LONG         i;
  215.     UWORD         x,y,Left,Top;
  216.  
  217.     SetFont(RenderInfo->gpr_RPort,Info->Font);
  218.  
  219.     Left    = ((struct Gadget *)object)->LeftEdge;
  220.     Top        = ((struct Gadget *)object)->TopEdge;
  221.  
  222.     SetAPen(RenderInfo->gpr_RPort,RenderInfo->gpr_GInfo->gi_DrInfo->dri_Pens[BACKGROUNDPEN]);
  223.     RectFill(RenderInfo->gpr_RPort,Left,Top,Left + ((struct Gadget *)object)->Width - 1,Top + ((struct Gadget *)object)->Height - 1);
  224.  
  225.     DrawGrid(RenderInfo->gpr_RPort,Left,Top,RenderInfo->gpr_GInfo,Info);
  226.  
  227.     for(i = 0 ; i < Info -> NumLabels ; i++)
  228.     {
  229.         x = (i % Info->Width) * Info->CellWidth;
  230.         y = (i / Info->Width) * Info->CellHeight;
  231.  
  232.         DrawCellText(RenderInfo->gpr_RPort,Left + x,Top + y,Info->CellWidth,Info->CellHeight,Info->Labels[i]);
  233.     }
  234.  
  235.     return(TRUE);
  236. }
  237.  
  238. STATIC ULONG __regargs
  239. DisposeMethod(struct IClass *class,Object *object,Msg msg)
  240. {
  241.     MatrixInfo *Info = INST_DATA(class,object);
  242.  
  243.     if(Info->Font)
  244.         CloseFont(Info->Font);
  245.  
  246.     return(DoSuperMethodA(class,object,msg));
  247. }
  248.  
  249. STATIC ULONG __regargs
  250. NewMethod(struct IClass *class,Object *object,struct opSet *SetInfo)
  251. {
  252.     if(object = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo))
  253.     {
  254.         MatrixInfo        *Info = INST_DATA(class,object);
  255.         struct TagItem    *Tag,*TagList = SetInfo -> ops_AttrList;
  256.         struct TextAttr    *Font;
  257.         UWORD             Width,Height;
  258.  
  259.         Width = Height = 0;
  260.         Font = NULL;
  261.  
  262.         memset(Info,0,sizeof(MatrixInfo));
  263.  
  264.         while(Tag = NextTagItem(&TagList))
  265.         {
  266.             switch(Tag->ti_Tag)
  267.             {
  268.                 case MIA_CellWidth:
  269.                     Info->CellWidth = Tag->ti_Data;
  270.                     break;
  271.  
  272.                 case MIA_CellHeight:
  273.                     Info->CellHeight = Tag->ti_Data;
  274.                     break;
  275.  
  276.                 case MIA_Width:
  277.                     Info->Width = Tag->ti_Data;
  278.                     break;
  279.  
  280.                 case MIA_Height:
  281.                     Info->Height = Tag->ti_Data;
  282.                     break;
  283.  
  284.                 case MIA_Labels:
  285.                     Info->Labels = (STRPTR *)Tag->ti_Data;
  286.                     break;
  287.  
  288.                 case MIA_NumLabels:
  289.                     Info->NumLabels = Tag->ti_Data;
  290.                     break;
  291.  
  292.                 case MIA_Font:
  293.                     Font = (struct TextAttr *)Tag->ti_Data;
  294.                     break;
  295.  
  296.                 case GA_Width:
  297.                     Width = Tag->ti_Data;
  298.                     break;
  299.  
  300.                 case GA_Height:
  301.                     Height = Tag->ti_Data;
  302.                     break;
  303.             }
  304.         }
  305.  
  306.         if(Info->Labels && !Info->NumLabels)
  307.         {
  308.             while(Info->Labels[Info->NumLabels])
  309.                 Info->NumLabels++;
  310.         }
  311.  
  312.         if(Font && Info->CellWidth && Info->CellHeight)
  313.         {
  314.             if(!Info->Width)
  315.                 Info->Width = Width / Info->CellWidth;
  316.  
  317.             if(!Info->Height)
  318.                 Info->Height = Height / Info->CellHeight;
  319.  
  320.             if(Info->Width && Info->Height)
  321.             {
  322.                 if(Info->Font = OpenFont(Font))
  323.                 {
  324.                     Info->CurrentX        = -1;
  325.                     Info->CurrentY        = -1;
  326.                     Info->PixelWidth    = Info->Width    * Info->CellWidth;
  327.                     Info->PixelHeight    = Info->Height    * Info->CellHeight;
  328.  
  329.                     return((ULONG)object);
  330.                 }
  331.             }
  332.         }
  333.  
  334.         CoerceMethod(class,object,OM_DISPOSE);
  335.     }
  336.  
  337.     return(0);
  338. }
  339.  
  340. STATIC ULONG __regargs
  341. InputMethod(struct IClass *class,Object *object,struct gpInput *InputInfo)
  342. {
  343.     MatrixInfo    *Info    = INST_DATA(class,object);
  344.     ULONG         Result    = GMR_MEACTIVE;
  345.     BOOL         Done    = FALSE;
  346.     WORD         x,y;
  347.  
  348.     if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
  349.     {
  350.         if(InputInfo -> gpi_IEvent -> ie_Code == MENUDOWN)
  351.         {
  352.             Result    = GMR_NOREUSE;
  353.             Done    = TRUE;
  354.         }
  355.         else
  356.         {
  357.             if(InputInfo -> gpi_IEvent -> ie_Code == SELECTUP)
  358.             {
  359.                 Done = TRUE;
  360.  
  361.                 if(Info -> CurrentX != -1 && Info -> CurrentY != -1)
  362.                 {
  363.                     Result = GMR_REUSE | GMR_VERIFY;
  364.  
  365.                     *InputInfo -> gpi_Termination = Info -> CurrentY * Info -> Width + Info -> CurrentX;
  366.                 }
  367.                 else
  368.                     Result = GMR_NOREUSE;
  369.             }
  370.         }
  371.  
  372.         if(Done && Info -> CurrentX != -1 && Info -> CurrentY != -1)
  373.         {
  374.             struct RastPort    *RPort;
  375.  
  376.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  377.             {
  378.                 SetFont(RPort,Info->Font);
  379.  
  380.                 DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InputInfo->gpi_GInfo,Info,Info->CurrentX,Info->CurrentY,FALSE);
  381.  
  382.                 Info->CurrentX    = -1;
  383.                 Info->CurrentY    = -1;
  384.  
  385.                 ReleaseGIRPort(RPort);
  386.  
  387.                 NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,-1);
  388.             }
  389.         }
  390.     }
  391.  
  392.     if(!Done)
  393.     {
  394.         x    = InputInfo->gpi_Mouse . X / Info->CellWidth;
  395.         y    = InputInfo->gpi_Mouse . Y / Info->CellHeight;
  396.  
  397.         if(InputInfo->gpi_Mouse . X < 0 || InputInfo->gpi_Mouse . Y < 0 || x >= Info->Width || y >= Info->Height)
  398.             x = y = -1;
  399.  
  400.         if(x != Info->CurrentX || y != Info->CurrentY)
  401.         {
  402.             struct RastPort    *RPort;
  403.  
  404.             if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  405.             {
  406.                 SetFont(RPort,Info->Font);
  407.  
  408.                 if(Info->CurrentX != -1 && Info->CurrentY != -1)
  409.                     DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InputInfo->gpi_GInfo,Info,Info->CurrentX,Info->CurrentY,FALSE);
  410.  
  411.                 Info->CurrentX    = x;
  412.                 Info->CurrentY    = y;
  413.  
  414.                 if(x != -1 && y != -1)
  415.                 {
  416.                     DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InputInfo->gpi_GInfo,Info,Info->CurrentX,Info->CurrentY,TRUE);
  417.  
  418.                     NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,y * Info->Width + x);
  419.                 }
  420.                 else
  421.                     NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,-1);
  422.  
  423.                 ReleaseGIRPort(RPort);
  424.             }
  425.         }
  426.     }
  427.  
  428.     return(Result);
  429. }
  430.  
  431. STATIC ULONG __regargs
  432. ActiveMethod(struct IClass *class,Object *object,struct gpInput *InputInfo)
  433. {
  434.     MatrixInfo        *Info = INST_DATA(class,object);
  435.     struct RastPort    *RPort;
  436.  
  437.     if(RPort = ObtainGIRPort(InputInfo->gpi_GInfo))
  438.     {
  439.         SetFont(RPort,Info->Font);
  440.  
  441.         if(Info->CurrentX != -1 && Info->CurrentY !=-1)
  442.             DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InputInfo->gpi_GInfo,Info,Info->CurrentX,Info->CurrentY,FALSE);
  443.  
  444.         Info->CurrentX    = InputInfo->gpi_Mouse . X / Info->CellWidth;
  445.         Info->CurrentY    = InputInfo->gpi_Mouse . Y / Info->CellHeight;
  446.  
  447.         if(Info->CurrentX > Info->Width - 1)
  448.             Info->CurrentX = Info->Width - 1;
  449.         else
  450.         {
  451.             if(Info->CurrentX < 0)
  452.                 Info->CurrentX = 0;
  453.         }
  454.  
  455.         if(Info->CurrentY > Info->Height - 1)
  456.             Info->CurrentY = Info->Height - 1;
  457.         else
  458.         {
  459.             if(Info->CurrentY < 0)
  460.                 Info->CurrentY = 0;
  461.         }
  462.  
  463.         DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InputInfo->gpi_GInfo,Info,Info->CurrentX,Info->CurrentY,TRUE);
  464.  
  465.         NotifyIndex(class,object,InputInfo->gpi_GInfo,(struct opUpdate *)InputInfo,Info->CurrentY * Info->Width + Info->CurrentX);
  466.  
  467.         ReleaseGIRPort(RPort);
  468.  
  469.         return(GMR_MEACTIVE);
  470.     }
  471.     else
  472.         return(GMR_NOREUSE);
  473. }
  474.  
  475. STATIC ULONG __regargs
  476. InactiveMethod(struct IClass *class,Object *object,struct gpGoInactive *InactiveInfo)
  477. {
  478.     MatrixInfo *Info = INST_DATA(class,object);
  479.  
  480.     if(Info -> CurrentX != -1 && Info -> CurrentY != -1)
  481.     {
  482.         struct RastPort    *RPort;
  483.  
  484.         if(RPort = ObtainGIRPort(InactiveInfo->gpgi_GInfo))
  485.         {
  486.             SetFont(RPort,Info->Font);
  487.  
  488.             DrawCell(RPort,((struct Gadget *)object) -> LeftEdge,((struct Gadget *)object) -> TopEdge,InactiveInfo->gpgi_GInfo,Info,Info->CurrentX,Info->CurrentY,FALSE);
  489.  
  490.             ReleaseGIRPort(RPort);
  491.  
  492.             NotifyIndex(class,object,InactiveInfo->gpgi_GInfo,(struct opUpdate *)InactiveInfo,-1);
  493.         }
  494.     }
  495.  
  496.     Info -> CurrentX = -1;
  497.     Info -> CurrentY = -1;
  498.  
  499.     return(0);
  500. }
  501.  
  502. STATIC ULONG __regargs
  503. HitTestMethod(struct IClass *class,Object *object,struct gpHitTest *HitInfo)
  504. {
  505.     MatrixInfo *Info = INST_DATA(class,object);
  506.  
  507.     if(HitInfo -> gpht_Mouse . X < Info -> PixelWidth && HitInfo -> gpht_Mouse . Y < Info -> PixelHeight)
  508.         return(GMR_GADGETHIT);
  509.     else
  510.         return(0);
  511. }
  512.  
  513. STATIC ULONG __saveds __asm
  514. Dispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  515. {
  516.     switch(msg->MethodID)
  517.     {
  518.         case OM_NEW:
  519.             return(NewMethod(class,object,(struct opSet *)msg));
  520.  
  521.         case OM_UPDATE:
  522.         case OM_SET:
  523.             return(SetMethod(class,object,(struct opSet *)msg));
  524.  
  525.         case OM_DISPOSE:
  526.             return(DisposeMethod(class,object,msg));
  527.  
  528.         case GM_RENDER:
  529.             return(RenderMethod(class,object,(struct gpRender *)msg));
  530.  
  531.         case GM_HITTEST:
  532.             return(HitTestMethod(class,object,(struct gpHitTest *)msg));
  533.  
  534.         case GM_GOINACTIVE:
  535.             return(InactiveMethod(class,object,(struct gpGoInactive *)msg));
  536.  
  537.         case GM_GOACTIVE:
  538.             return(ActiveMethod(class,object,(struct gpInput *)msg));
  539.  
  540.         case GM_HANDLEINPUT:
  541.             return(InputMethod(class,object,(struct gpInput *)msg));
  542.  
  543.         default:
  544.             return(DoSuperMethodA(class,object,msg));
  545.     }
  546. }
  547.  
  548. STATIC VOID
  549. DeleteMatrixClass(VOID)
  550. {
  551.     if(MatrixClass)
  552.     {
  553.         FreeClass(MatrixClass);
  554.         MatrixClass = NULL;
  555.     }
  556. }
  557.  
  558. STATIC struct IClass *
  559. CreateMatrixClass(VOID)
  560. {
  561.     if(MatrixClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(MatrixInfo),0))
  562.         MatrixClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)Dispatch;
  563.  
  564.     return(MatrixClass);
  565. }
  566.  
  567. VOID
  568. CloseMatrixWindow()
  569. {
  570.     CheckItem(MEN_MATRIX_WINDOW,FALSE);
  571.  
  572.     if(MatrixWindow)
  573.     {
  574.         ClearMenuStrip(MatrixWindow);
  575.  
  576.         CloseWindowSafely(MatrixWindow);
  577.  
  578.         MatrixWindow = NULL;
  579.     }
  580.  
  581.     if(MatrixGadget)
  582.     {
  583.         DisposeObject(MatrixGadget);
  584.  
  585.         MatrixGadget = NULL;
  586.     }
  587.  
  588.     DeleteMatrixClass();
  589. }
  590.  
  591. BOOL
  592. DispatchMatrixWindow(ULONG *MsgClass,UWORD MsgCode,ULONG MsgQualifier,UBYTE Char)
  593. {
  594.     if(MatrixWindow)
  595.     {
  596.         switch(*MsgClass)
  597.         {
  598.             case IDCMP_RAWKEY:
  599.  
  600.                 if(!(MsgCode & IECODE_UP_PREFIX) && !(MsgQualifier & IEQUALIFIER_REPEAT) && !(MsgCode >= CURSOR_UP_CODE && MsgCode <= F10_CODE) && !(MsgCode >= HELP_CODE && MsgCode <= RAMIGA_CODE))
  601.                 {
  602.                     SetGadgetAttrs((struct Gadget *)MatrixGadget,MatrixWindow,NULL,
  603.                         MIA_Index,    Char,
  604.                     TAG_DONE);
  605.  
  606.                     Delay(5);
  607.  
  608.                     SetGadgetAttrs((struct Gadget *)MatrixGadget,MatrixWindow,NULL,
  609.                         MIA_Index,    -1,
  610.                     TAG_DONE);
  611.                 }
  612.  
  613.                 break;
  614.  
  615.             case IDCMP_CLOSEWINDOW:
  616.  
  617.                 *MsgClass = 0;
  618.  
  619.                 return(TRUE);
  620.  
  621.             case IDCMP_GADGETUP:
  622.  
  623.                 *MsgClass = 0;
  624.  
  625.                 Char = MsgCode;
  626.  
  627.                 SerWrite(&Char,1);
  628.  
  629.                 break;
  630.  
  631.             case IDCMP_IDCMPUPDATE:
  632.  
  633.                 *MsgClass = 0;
  634.  
  635.                 if((WORD)MsgCode < 0)
  636.                     SetWindowTitles(MatrixWindow,LocaleString(MSG_MATRIX_WINDOW_TITLE),(STRPTR)~0);
  637.                 else
  638.                 {
  639.                     UBYTE    OctalBuffer[6],BinBuffer[10];
  640.                     WORD    i,Code;
  641.  
  642.                     OctalBuffer[0] = '0';
  643.  
  644.                     for(Code = MsgCode, i = 0 ; i < 3 ; i++)
  645.                     {
  646.                         OctalBuffer[2 - i + 1] = '0' + (Code & 7);
  647.  
  648.                         Code = Code >> 3;
  649.                     }
  650.  
  651.                     OctalBuffer[4] = 0;
  652.  
  653.                     BinBuffer[0] = '%';
  654.  
  655.                     for(Code = MsgCode, i = 0 ; i < 8 ; i++)
  656.                     {
  657.                         BinBuffer[7 - i + 1] = '0' + (Code & 1);
  658.  
  659.                         Code = Code >> 1;
  660.                     }
  661.  
  662.                     BinBuffer[9] = 0;
  663.  
  664.                     SPrintf(TitleBuffer,"%s [%ld · $%02lx · %s · %s]",LocaleString(MSG_MATRIX_WINDOW_TITLE),MsgCode,MsgCode,OctalBuffer,BinBuffer);
  665.  
  666.                     SetWindowTitles(MatrixWindow,TitleBuffer,(STRPTR)~0);
  667.                 }
  668.  
  669.                 break;
  670.         }
  671.     }
  672.  
  673.     return(FALSE);
  674. }
  675.  
  676. struct Window *
  677. OpenMatrixWindow(struct Window *Parent)
  678. {
  679.     if(MatrixWindow)
  680.     {
  681.         WindowToFront(MatrixWindow);
  682.  
  683.         ActivateWindow(MatrixWindow);
  684.  
  685.         return(MatrixWindow);
  686.     }
  687.     else
  688.     {
  689.         struct RastPort     RastPort;
  690.         struct TextFont    *Font;
  691.         LONG             i,MaxWidth,Width,Height;
  692.  
  693.         InitRastPort(&RastPort);
  694.         Font = OpenFont(&UserFont);
  695.         SetFont(&RastPort,Font);
  696.  
  697.         for(i = 0, MaxWidth = 0 ; i < 256 ; i++)
  698.         {
  699.             if((Width = TextLength(&RastPort,CharCodes[i],strlen(CharCodes[i]))) > MaxWidth)
  700.                 MaxWidth = Width;
  701.         }
  702.  
  703.         Width    = 2 + MaxWidth + 2;
  704.         Height    = 2 + RastPort . TxHeight + 2;
  705.  
  706.         if(Parent -> WScreen -> WBorTop + Parent -> WScreen -> Font -> ta_YSize + 1 + Parent -> WScreen -> WBorBottom + 16 * Height > Parent -> WScreen -> Height || Parent -> WScreen -> WBorLeft + 16 * Width + Parent -> WScreen -> WBorRight > Parent -> WScreen -> Width)
  707.         {
  708.             DisplayBeep(Parent -> WScreen);
  709.  
  710.             return(NULL);
  711.         }
  712.  
  713.         if(CreateMatrixClass())
  714.         {
  715.             STATIC Tag Map[] = { MIA_Index, ICSPECIAL_CODE, TAG_DONE };
  716.  
  717.             if(MatrixGadget = NewObject(MatrixClass,NULL,
  718.                 GA_Left,            Parent -> WScreen -> WBorLeft + 2,
  719.                 GA_Top,                Parent -> WScreen -> WBorTop + Parent -> WScreen -> Font -> ta_YSize + 1 + 2,
  720.                 GA_Width,            16 * Width,
  721.                 GA_Height,            16 * Height,
  722.                 GA_RelVerify,        TRUE,
  723.  
  724.                 ICA_TARGET,            ICTARGET_IDCMP,
  725.                 ICA_MAP,            Map,
  726.  
  727.                 MIA_Width,            16,
  728.                 MIA_Height,            16,
  729.                 MIA_CellWidth,        Width,
  730.                 MIA_CellHeight,        Height,
  731.                 MIA_Labels,            CharCodes,
  732.                 MIA_NumLabels,        256,
  733.                 MIA_Font,            &UserFont,
  734.             TAG_DONE))
  735.             {
  736.                 if(MatrixWindow = OpenWindowTags(NULL,
  737.                     WA_Top,                Parent -> TopEdge + Parent -> BorderTop,
  738.                     WA_Left,            Parent -> LeftEdge,
  739.                     WA_Title,            LocaleString(MSG_MATRIX_WINDOW_TITLE),
  740.                     WA_DepthGadget,        TRUE,
  741.                     WA_CloseGadget,        TRUE,
  742.                     WA_DragBar,            TRUE,
  743.                     WA_InnerWidth,        2 + (Width * 16) + 2,
  744.                     WA_InnerHeight,        2 + (Height * 16) + 2,
  745.                     WA_Activate,        TRUE,
  746.                     WA_Gadgets,            MatrixGadget,
  747.                     WA_CustomScreen,    Parent -> WScreen,
  748.                     WA_RMBTrap,            TRUE,
  749.                     WA_NewLookMenus,    TRUE,
  750.                     BackfillTag,        &BackfillHook,
  751.                     WA_SimpleRefresh,    TRUE,
  752.  
  753.                     AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  754.                     CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  755.                 TAG_DONE))
  756.                 {
  757.                     MatrixWindow -> UserPort = Parent -> UserPort;
  758.  
  759.                     if(ModifyIDCMP(MatrixWindow,Parent -> IDCMPFlags | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE | IDCMP_REFRESHWINDOW))
  760.                     {
  761.                         SetMenuStrip(MatrixWindow,Menu);
  762.  
  763.                         MatrixWindow -> Flags &= ~WFLG_RMBTRAP;
  764.  
  765.                         CheckItem(MEN_MATRIX_WINDOW,TRUE);
  766.  
  767.                         return(MatrixWindow);
  768.                     }
  769.  
  770.                     MatrixWindow -> UserPort = NULL;
  771.  
  772.                     CloseWindow(MatrixWindow);
  773.  
  774.                     MatrixWindow = NULL;
  775.                 }
  776.  
  777.                 DisposeObject(MatrixGadget);
  778.  
  779.                 MatrixGadget = NULL;
  780.             }
  781.  
  782.             DeleteMatrixClass();
  783.         }
  784.  
  785.         CheckItem(MEN_MATRIX_WINDOW,FALSE);
  786.  
  787.         return(NULL);
  788.     }
  789. }
  790.